/**
 * @project: parallel-task
 * @package: com.ngplat.paralleltask.utils
 * @filename: TaskXmlParser.java
 *
 * Copyright (c) 2018 eSunny Info. Tech Ltd. All rights reserved.
 * 
 */
package com.ngplat.paralleltask.utils;

import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ngplat.paralleltask.constants.TaskState;
import com.ngplat.paralleltask.model.TaskInfo;

/**
 * @typename: TaskXmlParser
 * @brief: 不具有通用性, 解析xml, 生成TaskInfo信息
 * @author: KI ZCQ
 * @date: 2018年5月31日 上午9:16:13
 * @version: 1.0.0
 * @since
 * 
 */
public class TaskXmlParser {

	private static Logger logger = LoggerFactory.getLogger(TaskXmlParser.class);
	
	/**
	 * @Description: 解析生成TaskInfo
	 * @param xmlFilePath
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static List<TaskInfo> parseTaskXml(String xmlFilePath) {
		// 创建一个SAXReader对象
		SAXReader sax = new SAXReader();
		// 根据指定的路径创建file对象
		File xmlFile = new File(xmlFilePath);

		// 创建list集合
		List<TaskInfo> list = new ArrayList<TaskInfo>();
		try {
			// 获取document对象,如果文档无节点，则会抛出Exception提前结束
			Document document = sax.read(xmlFile);
			// 获取根节点
			Element root = document.getRootElement();
			// 获得实例的属性
			Field[] properties = TaskInfo.class.getDeclaredFields();

			// 获取一级节点
			List<Element> jobElement = root.elements();
			// 遍历所有一级子节点
			for (Element job : jobElement) {
				String jobId = job.attributeValue("id");

				// 获取二级节点
				List<Element> taskElement = job.elements();
				// 遍历所有二级子节点
				for (Element task : taskElement) {
					// 获得对象的新的实例
					TaskInfo info = new TaskInfo();
					// 设置jobId
					info.setJobId(jobId);
					// 设置任务Id
					info.setTaskId(task.attributeValue("taskId"));
					// 遍历所有孙子节点
					for (int j = 0; j < properties.length; j++) {
						// 节点值
						String eleValue = task.elementText(properties[j].getName());
						if (eleValue != null) {
							// 
							setValueByType(info, properties[j], eleValue);
						}
					}
					// 添加结果集
					list.add(info);
				}
			}
		} catch (Exception e) {
			logger.error("解析任务xml文件{}出现异常, 请查看错误详情: {}", xmlFilePath, e);
			return new ArrayList<>();
		}

		return list;
	}

	/**
	 * 
	 * @Description:通过属性生成set方法名
	 * @param str
	 * @return
	 */
	public static String setMethodName(String str) {
		return "set" + firstToUpperCase(str);
	}

	/**
	 * @Description: 首字母大写
	 * @param str
	 * @return
	 */
	public static String firstToUpperCase(String str) {
		return Character.toUpperCase(str.charAt(0)) + str.substring(1);
	}
	
	/**
	 * @Description: 通过反射设置属性值
	 * @param obj
	 * @param field
	 * @param value
	 */
	private static void setValueByType(final Object obj, final Field field, String value) {
		
		if(field == null) {
			throw new NullPointerException("field is null.");
		}
		// 得到此属性的类型 
		String type = field.getType().getName();
		// 属性名
		String fieldName = field.getName();
		
		if (type.endsWith("String")) {
			Reflections.setFieldValue(obj, fieldName, value);
		} else if (type.equals("int") || type.endsWith("Integer")) {
			Reflections.setFieldValue(obj, fieldName, Integer.parseInt(value));
		} else if (type.equals("[Ljava.lang.String;")) {
			Reflections.invokeMethodByName(obj, setMethodName(fieldName), new Object[] {value.split(",")});
		} else if (type.endsWith("TaskState")) {
			Reflections.setFieldValue(obj, fieldName, TaskState.valueOf(value));
		} else {
			throw new IllegalArgumentException("can not support this type: " + type + " , info: " + obj.toString());
		}
	}

	public static void main(String[] args) {
		// xml path
		String path = XmlUtils.class.getClassLoader().getResource("xml/task_xml_template.xml").getPath();
		TaskXmlParser.parseTaskXml(path);
	}

}
